<template>
	<view class="pull-loading" :style="{ height: `${height}rpx` }" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
		<view class="pull-header" :class="{ animation: down.animation }" :style="{ height: `${down.height}rpx` }">
			<view class="inner" :style="{ opacity: `${down.height / 80}`, transform: `scale(${getLoadingScale})` }">
				<view class="icon" :class="{ loading: startLoading }"></view>
				<view class="text">数据加载中</view>
			</view>
		</view>
		<view class="pull-body"><slot></slot></view>
		<view v-if="allowPullUp" class="pull-footer" :class="{ line: status === 2 }" :style="{ height: footerHeight + 'rpx' }">
			<view v-if="status === 1" class="icon"></view>
			<view class="text" @click="loadMoreClick">{{ statusText[status] }}</view>
		</view>
	</view>
</template>

<script>
import http from '../../common/request.js';
export default {
	props: {
		allowPullDown: { type: Boolean, default: true },
		allowPullUp: { type: Boolean, default: true },
		options: {
			type: Object,
			default() {
				return {};
			}
		},
		result: {
			type: Array,
			default() {
				return [];
			}
		}
	},
	data() {
		const info = uni.getSystemInfoSync();
		const ratio = 750 / info.windowWidth;
		return {
			height: info.windowHeight * ratio,
			footerHeight: 80,
			touch: {},
			down: {
				animation: false,
				height: 0
			},
			status: 0,
			statusText: { 0: '点击加载更多', 1: '加载中', 2: '我是有底线的', 3: '暂无数据' },
			scrollTop: 0,
			allowRequest: true
		};
	},
	computed: {
		getLoadingScale() {
			return this.calcIsPullDownEnd();
		},
		startLoading() {
			return this.calcIsPullDownEnd() === 1 ? true : false;
		}
	},
	created() {
		if(this.allowPullUp) {
			this.request();
		}
	},
	methods: {
		calcIsPullDownEnd() {
			return this.down.height / 80;
		},
		touchstart(e) {
			this.touch.allow = true;
			this.touch.start = e.touches[0].pageY;
		},
		touchmove(e) {
			const current = e.touches[0].pageY;
			const move = current - this.touch.start;
			if (move > 0) {
				this.down.height = move < 80 ? move : 80;
			}
			this.move = move;
		},
		touchend() {
			if (this.move < 80) {
				this.cancelPullDownLoading();
			} else {
				setTimeout(r => this.stopPullDownLoading(), 1000);
			}
		},
		cancelPullDownLoading() {
			this.down.height = 0;
		},
		stopPullDownLoading() {
			this.down.animation = true;
			setTimeout(() => {
				this.down.height = 0;
				this.down.animation = false;
			}, 600);
		},
		request() {
			const { options = {} } = this;
			const url = options.url || '';
			const { pageNum = 1, pageSize = 10, data = {}, method = 'GET' } = options;
			const opt = {
				method,
				data: { ...data, pageNum, pageSize }
			};
			if (this.allowRequest) {
				this.allowRequest = false;
			} else {
				return; //请求中时，禁止再次发送请求，防止本次请求数据被覆盖
			}
			this.status = 1;
			http(url, {
				method: 'GET',
				...opt
			})
				.then(result => {
					if (result.code === 200) {
						const list = result.data || [];
						if (list.length < pageSize) {
							this.status = 2;
						} else {
							this.status = 0;
							this.allowRequest = true;
						}
						const all = [...this.result, ...list];
						this.$emit('update:result', all);

						if (all.length === 0) {
							//没有数据就禁止再次请求
							this.status = 3;
							this.allowRequest = false;
						}
					}
				})
				.catch(r => {
					this.status = 0;
					this.allowRequest = true;
				});
		},
		loadMoreClick() {
			if (this.status === 0) {
				this.request();
			}
		}
	}
};
</script>

<style lang="less" scoped>
@keyframes rotate {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(360deg);
	}
}
@keyframes fadeout {
	to {
		height: 0;
	}
}
@keyframes scale {
	from {
		transform: scale(1);
	}
	to {
		transform: scale(0);
	}
}
.pull-loading {
	background-color: #fff;
	.pull-header {
		display: flex;
		align-items: center;
		justify-content: center;
		overflow: hidden;
		background-color: #f1f1f1;
		&.animation {
			animation: fadeout 0.6s;
			animation-fill-mode: forwards;
			.inner {
				animation: scale 0.6s;
				animation-fill-mode: forwards;
			}
		}
		.inner {
			display: flex;
			align-items: center;
			justify-content: center;
			.icon {
				background-image: url();
				background-position: center;
				background-size: 100%;
				background-repeat: no-repeat;
				width: 28rpx;
				height: 28rpx;
				&.loading {
					animation: rotate 0.6s infinite linear;
				}
			}
			.text {
				margin-left: 8rpx;
				font-size: 22rpx;
				font-weight: 400;
				color: #8a8c8d;
				line-height: 30rpx;
			}
		}
	}
	.pull-body {
	}
	.pull-footer {
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 24rpx;
		color: #66645d;
		&.line {
			&::before,
			&::after {
				content: '';
				width: 90rpx;
				height: 2rpx;
				transform: scaleY(0.5);
				background-color: #8a8a8a;
				margin: 0 10rpx;
			}
		}
		.icon {
			background-image: url();
			background-position: center;
			background-size: 100%;
			background-repeat: no-repeat;
			width: 28rpx;
			height: 28rpx;
			margin-right: 6rpx;
			animation: rotate 0.6s infinite linear;
		}
	}
}
</style>
